package org.apache.shardingsphere.elasticjob.lite.ui.web.controller;

import org.apache.commons.lang.StringUtils;
import org.apache.shardingsphere.elasticjob.lite.ui.domain.UserManage;
import org.apache.shardingsphere.elasticjob.lite.ui.dto.request.UserManageRequest;
import org.apache.shardingsphere.elasticjob.lite.ui.exception.JobConsoleException;
import org.apache.shardingsphere.elasticjob.lite.ui.security.UserAccount;
import org.apache.shardingsphere.elasticjob.lite.ui.service.UserManageService;
import org.apache.shardingsphere.elasticjob.lite.ui.util.SessionUtils;
import org.apache.shardingsphere.elasticjob.lite.ui.web.response.ResponseResult;
import org.apache.shardingsphere.elasticjob.lite.ui.web.response.ResponseResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;

/**
 * @Description user manage controller
 * @Author JL
 */
@RestController
@RequestMapping("/api/user")
public class UserManageController {

    private UserManageService userManageService;
    private SessionUtils sessionUtils;

    @Value("${auth.root_username:root}")
    private String authAccount;

    @Autowired
    public UserManageController(final UserManageService userManageService, final SessionUtils sessionUtils) {
        this.userManageService = userManageService;
        this.sessionUtils = sessionUtils;
    }

    /**
     * Get all user info.
     *
     * @return all user info
     */
    @GetMapping("/list")
    public ResponseResult<Collection<UserManage>> userList(@RequestParam("account") final String account) {
        if (StringUtils.isNotBlank(account)){
            return ResponseResultUtil.build(userManageService.search(account).getUserManage());
        }
        return ResponseResultUtil.build(userManageService.loadAll().getUserManage());
    }

    /**
     * save user.
     *
     * @param loginUser user account
     */
    @PostMapping("/save")
    public ResponseResult<Boolean> saveUser(@RequestBody UserManage loginUser) {
        if (loginUser == null){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "request body can't not null!");
        }
        if (StringUtils.isBlank(loginUser.getAccount())){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "user account can't not null!");
        }
        if (StringUtils.isBlank(loginUser.getUserName())){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "user userName can't not null!");
        }
        if (StringUtils.isBlank(loginUser.getUserName())){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "user password can't not null!");
        }
        if (StringUtils.isBlank(loginUser.getStatus())){
            loginUser.setStatus("DISABLED");
        }
        if (userManageService.load(loginUser.getAccount()) != null){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "user account：".concat(loginUser.getAccount()).concat(" is exist!"));
        }
        userManageService.save(loginUser);
        return ResponseResultUtil.build(Boolean.TRUE);
    }

    /**
     * devolve user config
     * @param userManageRequest
     * @return
     */
    @PostMapping(value = "/devolve")
    public ResponseResult<Boolean> devolveUser(@RequestBody UserManageRequest userManageRequest) {
        if (userManageRequest == null){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "request body can't not null!");
        }
        if (StringUtils.isBlank(userManageRequest.getFromAccount())){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "user a account can't not null!");
        }
        if (StringUtils.isBlank(userManageRequest.getToAccount())){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "user b account can't not null!");
        }
        // need root account
        UserAccount userAccount = sessionUtils.getSessionUser();
        if (!authAccount.equals(userAccount.getUsername())){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "need root account can update!");
        }
        String fromAccount = userManageRequest.getFromAccount();
        String toAccount = userManageRequest.getToAccount();
        if (userManageService.load(toAccount) == null){
            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, "user account：".concat(toAccount).concat(" not exist!"));
        }
        //clean session config
        sessionUtils.cleanEventTraceDataSourceConfiguration(userManageRequest.getFromAccount());
        sessionUtils.cleanRegistryCenterConfiguration(fromAccount);
        userManageService.devolve(fromAccount, toAccount);
        return ResponseResultUtil.build(Boolean.TRUE);
    }

    /**
     * Disable user.
     *
     * @param account user account
     */
    @PostMapping(value = "/{account}/disable")
    public ResponseResult<Boolean> disableUser(@PathVariable("account") final String account) {
        userManageService.disable(account);
        return ResponseResultUtil.build(Boolean.TRUE);
    }

    /**
     * Enable user.
     *
     * @param account user account
     */
    @PostMapping(value = "/{account}/enable")
    public ResponseResult<Boolean> enableUser(@PathVariable("account") final String account) {
        userManageService.enable(account);
        return ResponseResultUtil.build(Boolean.TRUE);
    }

    /**
     * Delete user.
     *
     * @param account user account
     */
    @DeleteMapping(value = "/{account}/delete")
    public ResponseResult<Boolean> deleteUser(@PathVariable("account") final String account) {
        userManageService.delete(account);
        return ResponseResultUtil.build(Boolean.TRUE);
    }
}
